<?php

namespace app\admin\controller\yungift\gift;

use addons\yungift\model\GiftMain;
use addons\yungift\model\GiftSpec;
use addons\yungift\library\Super;
use addons\yungift\model\ImportLog as ImportLogModel;
use app\admin\model\yungift\GiftCode;
use app\common\controller\Backend;
use fast\Random;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use think\Exception;

/**
 * 礼品 - 券码
 */
class Code extends Backend
{
    /**
     * @var GiftCode
     */
    protected $model;

    // 联表查询，解决字段冲突
    protected $relationSearch = true;

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new GiftCode();

        // 礼品规格列表
        $giftSpecList = GiftSpec::getOptionList($this->request->request('gift_id'));
        $this->view->assign('giftSpecList', $giftSpecList);
        $this->assignconfig('giftSpecList', $giftSpecList);

        // 类型和状态
        $this->view->assign('statusList', $this->model::getStatusList());
        $this->assignconfig('statusList', $this->model::getStatusList());
    }

    /**
     * 查看
     */
    public function index()
    {
        $giftId = $this->request->request('gift_id');
        if (! $gift = GiftMain::get($giftId)) {
            $this->error(__('礼品不存在'));
        }
        if ($this->request->isAjax()) {
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
            $list = $this->model->with(['giftData', 'giftSpecData'])->where(['gift_id' => $giftId])
                ->where($where)->order($sort, $order)->limit($offset, $limit)->paginate($limit);
            foreach ($list as $item) {
                $item->append(['data_mix'])->hidden(['data']);
            }
            $result = array(
                'total' => $list->total(),
                'rows'  => $list->items(),
            );

            return json($result);
        }

        return $this->view->fetch(null, ['gift' => $gift]);
    }


    /**
     * 数据导入
     *
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
     */
    public function import()
    {
        // 超时、超内存设置
        ini_set('memory_limit', '1024M');
        ini_set('max_execution_time', '0');

        $giftId = $this->request->request('gift_id');
        if (! $giftId) {
            $this->error(__('礼品未选择，不能直接导入'));
        }
        if (! $gift = GiftMain::get($giftId)) {
            $this->error(__('礼品无效，不能直接导入'));
        }

        // 获取文件路径
        $file = $this->request->request('file');
        if (! $file) {
            $this->error(__('Parameter %s can not be empty', 'file'));
        }
        $filePath = ROOT_PATH . DS . 'public' . DS . $file;
        if (! is_file($filePath)) {
            $this->error(__('No results were found'));
        }

        // 新增导入结果
        ImportLogModel::create([
            'scene'       => ImportLogModel::SCENE_GIFT_CODE,
            'import_file' => $file,
            'status'      => ImportLogModel::STATUS_HANDLE
        ]);

        // 实例化reader，并读取文件
        $ext = pathinfo($filePath, PATHINFO_EXTENSION);
        if ($ext !== 'xlsx') {
            $this->error(__('Unknown data format'));
        }
        $reader = new Xlsx();
        if (! $spreadsheet = $reader->load($filePath)) {
            $this->error(__('Unknown data format'));
        }
        $currentSheet = $spreadsheet->getSheet(0);  // 读取文件中的第一个工作表
        $allColumn = $currentSheet->getHighestDataColumn();  // 取得最大的列号
        $allRow = $currentSheet->getHighestRow();  // 取得一共有多少行
        $maxColumnNumber = Coordinate::columnIndexFromString($allColumn);  // 取得最大的列数字
        if ($allRow <= 2) {
            $this->error(__('No rows were updated'));
        }
        $firstHead = $currentSheet->getCellByColumnAndRow(1, 2)->getValue();
        if ($firstHead !== '规格') {
            $this->error(__('数据表头不对'));
        }

        $counter = [];
        try {
            // 获取数据
            $dataList = [];
            for ($currentRow = 3; $currentRow <= $allRow; $currentRow++) {
                $values = [];
                for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
                    $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
                    $values[] = is_null($val) ? '' : trim($val);
                }
                $dataList[] = $values;
            }

            // 设置标题
            $this->setSheetCellValue($currentSheet, -1, '导入结果');
            $currentSheet->getCellByColumnAndRow(3, 2)->getStyle()->applyFromArray([
                'font'      => [
                    'name'  => 'Arial',
                    'color' => ['rgb' => '000000'],
                    'size'  => 12,
                    'bold'  => true
                ],
                'alignment' => [
                    'horizontal' => Alignment::HORIZONTAL_CENTER,
                    'vertical'   => Alignment::VERTICAL_CENTER,
                ]
            ]);

            // 处理数据
            // 列对应关系：0=规格，1=券码
            foreach ($dataList as $index => $item) {
                if (empty($item[1])) {
                    Super::counter($counter, '券码为空');
                    continue;
                }
                $giftSpecId = 0;
                if ($item[0] !== '无' && $item[0]) {
                    if (! $gift->multi_spec) {
                        $this->setSheetCellValue($currentSheet, $index, '不应有规格', 1, $counter);
                        continue;
                    }
                    if (! $giftSpec = GiftSpec::get(['gift_id' => $giftId, 'name' => $item[0]])) {
                        $this->setSheetCellValue($currentSheet, $index, '规格不对', 1, $counter);
                        continue;
                    }
                    $giftSpecId = $giftSpec->id;
                } else {
                    if ($gift->multi_spec) {
                        $this->setSheetCellValue($currentSheet, $index, '必须有规格', 1, $counter);
                        continue;
                    }
                }
                if (empty($item[1])) {
                    $this->setSheetCellValue($currentSheet, $index, '券码不能为空', 1, $counter);
                    continue;
                }
                if (! GiftCode::get([
                    'gift_id'      => $giftId,
                    'gift_spec_id' => $giftSpecId,
                    'data'         => $item[1]
                ])) {
                    $giftCode = new GiftCode();
                    $giftCode->scenario = 'add';
                    $giftCode->gift_id = $giftId;
                    $giftCode->gift_spec_id = $giftSpecId;
                    $giftCode['data'] = $item[1];
                    $giftCode->status = GiftCode::STATUS_NORMAL;
                    $giftCode->allowField(true)->save();
                    $this->setSheetCellValue($currentSheet, $index, '新增数据', 0, $counter);
                    continue;
                }
                $this->setSheetCellValue($currentSheet, $index, '重复数据', 0, $counter);
            }

            // 生成excel文件
            $filePath = DS . 'uploads' . DS . date('Ymd') . DS . Random::alnum(32) . '.xlsx';
            $objWriter = IOFactory::createWriter($spreadsheet, 'Xlsx');
            $objWriter->save(ROOT_PATH . 'public' . $filePath);

            // 更新导入结果
            ImportLogModel::update([
                'result_file' => $filePath,
                'status'      => ImportLogModel::STATUS_FINISH
            ], [
                'scene'       => ImportLogModel::SCENE_GIFT_CODE,
                'import_file' => $file,
            ]);
        } catch (Exception $exception) {
            $this->error($exception->getMessage());
        }

        // 导入结果
        $content = ['处理成功<br>'];
        foreach ($counter as $key => $value) {
            $hasError = false;
            if (! in_array($key, ['新增数据', '重复数据'])) {
                $key .= '，导入失败';
                $hasError = true;
            }
            $cont = $key . '： ' . $value . '条';
            if ($hasError) {
                $cont = '<b style="color: yellow;">' . $cont . '</b>';
            }
            $content[] = $cont;
        }
        $content = implode('<br>', $content);

        $exportResult = $filePath;
        $content .= '<br><br><a href="' . $exportResult . '" target="_blank" style="color: yellow;"><b><i class="fa fa-download"></i> 下载导入结果</b></a>';

        $this->success($content);
    }

    /**
     * 设置表格内容
     *
     * @param $workSheet
     * @param $index
     * @param $value
     */
    private function setSheetCellValue(&$workSheet, $index, $value, $level = 0, &$counter = [])
    {
        if ($level != -1) {
            Super::counter($counter, $value);
        }
        if ($oldValue = $workSheet->getCellByColumnAndRow(3, $index + 3)->getValue()) {
            $value = $oldValue . '；' . $value;
        }
        $workSheet->setCellValueByColumnAndRow(3, $index + 3, $value);
        if (! $oldValue) {
            $workSheet->getCellByColumnAndRow(3, $index + 3)->getStyle()->applyFromArray([
                'font'      => [
                    'name'  => 'Arial',
                    'color' => ['rgb' => $level > 0 ? 'f75544' : '000000'],
                    'size'  => 12,
                ],
                'alignment' => [
                    'horizontal' => Alignment::HORIZONTAL_CENTER,
                    'vertical'   => Alignment::VERTICAL_CENTER,
                ]
            ]);
        }
    }

    // 导出数据
    public function export()
    {
        // 超时、超内存设置
        ini_set('memory_limit', '1024M');
        ini_set('max_execution_time', '0');

        if ($this->request->isPost()) {
            // 重载查询条件
            $search = $this->request->post('search');
            $ids = $this->request->post('ids');
            $filter = $this->request->post('filter');
            $op = $this->request->post('op');
            $columns = $this->request->post('columns');
            $giftId = $this->request->request('gift_id');
            if (! $giftId) {
                $this->error(__('礼品未选择，不能直接导出'));
            }

            // 初始化表
            $spreadsheet = new Spreadsheet();
            $worksheet = $spreadsheet->setActiveSheetIndex(0);
            $worksheet->getDefaultRowDimension()->setRowHeight(25);  // 设置默认行高
            $worksheet->getDefaultColumnDimension()->setAutoSize(true);  // 设置自动宽

            // 设置提示
            $worksheet->mergeCellsByColumnAndRow(1, 1, 12, 1);  // 合并单元格
            $tips = '注意：如果没有规格，填写无；有，则填写规格名称	';
            $worksheet->setCellValueByColumnAndRow(1, 1, $tips);
            $worksheet->getCellByColumnAndRow(1, 1)->getStyle()->applyFromArray([
                'font'      => [
                    'color' => ['rgb' => 'ff0000'],
                    'size'  => 12,
                ],
                'alignment' => [
                    'horizontal' => Alignment::HORIZONTAL_CENTER,
                    'vertical'   => Alignment::VERTICAL_CENTER,
                ]
            ]);

            // 设置标题
            foreach (['ID', '规格', '券码', '状态', '变更时间', '新增时间'] as $key => $value) {
                $worksheet->setCellValueByColumnAndRow($key + 1, 2, __($value));
                $worksheet->getCellByColumnAndRow($key + 1, 2)->getStyle()->applyFromArray([
                    'font'      => [
                        'name'  => 'Arial',
                        'color' => ['rgb' => '000000'],
                        'size'  => 12,
                        'bold'  => true
                    ],
                    'alignment' => [
                        'horizontal' => Alignment::HORIZONTAL_CENTER,
                        'vertical'   => Alignment::VERTICAL_CENTER,
                    ]
                ]);
            }
            $worksheet->getColumnDimensionByColumn(3)->setWidth(20);  // 设置宽度
            $worksheet->getColumnDimensionByColumn(5)->setWidth(20);  // 设置宽度
            $worksheet->getColumnDimensionByColumn(6)->setWidth(20);  // 设置宽度

            // 获取条件
            $whereIds = $ids === 'all' ? '1=1' : ['id' => ['in', explode(',', $ids)]];
            $this->request->get(['search' => $search, 'ids' => $ids, 'filter' => $filter, 'op' => $op]);
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();

            // 查询数据
            $row = 2;
            $this->model
                ->where(['gift_id' => $giftId])
                ->where($where)
                ->where($whereIds)
                ->chunk(100, function ($items) use (&$row, &$worksheet) {
                    foreach ($items as $item) {
                        $row++;
                        $col = 1;
                        // 题目
                        $values = Super::arrayGetSet($item, [
                            'id',
                            'spec_name'  => function ($sItem) {
                                return $sItem->gift_spec_id ? $sItem->giftSpecData->name : '无';
                            },
                            'data',
                            'status_text',
                            'updated_at' => function ($item) {
                                return date('Y-m-d H:i:s', $item->updated_at);
                            },
                            'created_at' => function ($item) {
                                return date('Y-m-d H:i:s', $item->created_at);
                            }
                        ]);

                        // 其他
                        foreach ($values as $value) {
                            $worksheet->setCellValueByColumnAndRow($col, $row, $value);
                            $worksheet->getStyleByColumnAndRow($col, $row)->getNumberFormat()
                                ->setFormatCode(NumberFormat::FORMAT_TEXT);
                            $worksheet->getCellByColumnAndRow($col, $row)->getStyle()->applyFromArray([
                                'alignment' => [
                                    'horizontal' => Alignment::HORIZONTAL_CENTER,
                                    'vertical'   => Alignment::VERTICAL_CENTER,
                                ]
                            ]);
                            $col++;
                        }
                    }
                });

            // 导出文件
            // Redirect output to a client’s web browser (Excel2007)
            $fileName = date('YmdHis');
            header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
            header('Content-Disposition: attachment;filename="' . $fileName . '.xlsx"');
            header('Cache-Control: max-age=0');
            // If you're serving to IE 9, then the following may be needed
            header('Cache-Control: max-age=1');
            // If you're serving to IE over SSL, then the following may be needed
            header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');  // always modified
            header('Cache-Control: cache, must-revalidate');  // HTTP/1.1
            header('Pragma: public');  // HTTP/1.0
            $objWriter = IOFactory::createWriter($spreadsheet, 'Xlsx');
            $objWriter->save('php://output');
            exit;
        }
    }
}
